package cz.vse.adventura.po1715.xkosd00_kostka.gui;

import cz.vse.adventura.po1715.xkosd00_kostka.hra.Hra;
import cz.pecinovsky.english.pojj.adv_framework.game_txt.IGame;

import java.awt.BorderLayout;
import java.awt.Point;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;

/*******************************************************************************
 * Instance třídy {@code GUI_01} představují
 * superjednoduché grafické uživatelské rozhraní umožňující hrát hry
 * vyhovující podmínkám rámce (frameworku) definovaného v balíčku
 * {@code cz.pecinovsky.english.pojj.adv_framework.game_txt},
 * tj. textové hry vyhovující požadavkům minulého semestru.
 *
 * @author    Dominik KOSTKA
 * @version   1.00.000
 */
public class GUI_01
{
//== KONSTANTNÍ ATRIBUTY TŘÍDY =================================================

    /** Souřadnice, na které se aplikační okno přesune po spuštění GUI.
     *  To má smysl především při zobrazování na sekundárním monitoru. */
    private static final Point POINT_0 = new Point(0, 0);       //(-600, 0);

    /** Konstanty používané při formátování vystupujícího textu. */
    private static final String
            PŘED_PŘÍKAZEM = "\n=============================================\n",
            ZA_PŘÍKAZEM   = "\n---------------------------------------------\n";

//== PROMĚNNÉ ATRIBUTY TŘÍDY ===================================================
//== STATICKÝ INICIALIZAČNÍ BLOK - STATICKÝ KONSTRUKTOR ========================
//== KONSTANTNÍ ATRIBUTY INSTANCÍ ==============================================

    /** Hra, která bude hrána prostřednictvím tohoto GUI. */
    private final IGame game;

    /** Aplikační okno spuštěného GUI. */
    private final JFrame appWindow = new JFrame("První okno");

    /** Komponenta, do které je zapisován text
     *  informující uživatele o průběhu hry. */
    private final JTextArea outputArea = new JTextArea(30, 45);

    /** Vstupní textové pole, do nějž uživatel zapisuje své příkazy. */
    private final JTextField inputField = new JTextField(25);

//== PROMĚNNÉ ATRIBUTY INSTANCÍ ================================================
//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ TŘÍDY ========================================
//== OSTATNÍ NESOUKROMÉ METODY TŘÍDY ===========================================

//##############################################################################
//== KONSTRUKTORY A TOVÁRNÍ METODY =============================================

    /***************************************************************************
     * Vytvoří novou instanci GUI,
     * která hned odstartuje komunikaci s hrou zadanou v parametru.
     *
     * @param game Hra, se kterou bude GUI komunikovat
     */
    public GUI_01(IGame game)
    {
        this.game = game;

        //Okno je inicializováno již v deklaraci, zde je pouze zviditelníme
        appWindow.setVisible(true);

        //Následující posunutí má smysl pouze při zobrazování
        //na druhém monitoru, který je umístněn vlevo od hlavního
        appWindow.setLocation(POINT_0);

        //Nastavujeme akci při stisku zavíracího tlačítka daného okna
        // EXIT_ON_CLOSE nastaví ukončení celé aplikace
        appWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Pouze pro domonstraci, v příští verzi jej zrušíme
        JButton button = new JButton("Tlačítko");

        //Každou komponentu musíme přidat do jejího kontejenru
        //JFrame má implicitního správce rozvežení BorderLayout
        //V druhém parametru říkáme tomuto správci, kam komponentu umístit
        appWindow.add(button,BorderLayout.NORTH);  //Umístit do severní zóny

        //Do centrální zóny umístíme pole s vystupujícím textem
        appWindow.add(outputArea, BorderLayout.CENTER);

        //Zakážeme editování výstupní oblasti, takže uživatel nebude moci
        //změnit vystupující text, ale bude jej moci zkopírovat do schránky
        outputArea.setEditable(false);

        //Do jižní zóny dáme vstupní pole, do nějž bude hráč zadávat příkazy
        appWindow.add(inputField, BorderLayout.SOUTH);

        //U vstupního pole musíme přihlásit posluchače, který bude čekat
        //na stisk klávesy Enter při fokusu na vstupní pole
        inputField.addActionListener(new TxfListener());

        //Zadáním přázdného příkazu odstartujeme hru
        String odpověď = game.executeCommand("");

        //... a uvítací zprávu vypíšeme do výstupní textové oblasti
        outputArea.setText(odpověď + "\n");

        //Naplněnému oknu nastavíme nejmenší velikost, která ještě
        //respektuje velikosti jednotlivých komponent uvnitř okna
        appWindow.pack();
    }



//== ABSTRAKTNÍ METODY =========================================================
//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ INSTANCÍ =====================================
//== OSTATNÍ NESOUKROMÉ METODY INSTANCÍ ========================================
//== SOUKROMÉ A POMOCNÉ METODY TŘÍDY ===========================================
//== SOUKROMÉ A POMOCNÉ METODY INSTANCÍ ========================================
//== INTERNÍ DATOVÉ TYPY =======================================================

    /***************************************************************************
     * Vnitřní třída, jejíž instance představují posluchače
     * vstupního textového pole čekající na stisk klávesy {@code Enter}
     * v okamžiku, kdy má pole fokus.
     */
    private class TxfListener implements ActionListener
    {
        /***********************************************************************
         * Zjistí aktuální text ve vstupním poli (= text zadaného příkazu),
         * zapíše jej do výstupní oblasti,
         * předá zadaný příkaz obsluhované hře ke zpracování
         * a do výstupního pole zapíše obdržený výsledek.
         *
         * @param e Objekt, který je schopen poskytnout informace o události,
         *          avšak v této verzi není využíván
         */
        @Override
        public void actionPerformed(ActionEvent e)
        {
            //Přečte text ve vstupním poli...
            String statement = inputField.getText();

            //... a vypíše jej za text ve výstupní oblasti oddělený
            outputArea.append(PŘED_PŘÍKAZEM + statement + ZA_PŘÍKAZEM);

            //Zjistí odpověď hry na zadaný příkaz...
            String answer = game.executeCommand(statement);

            //... a vypíše je do výstupní oblasti
            outputArea.append(answer + '\n');

            //Na závěr vyčistí vstupní pole pro zadání dalšího příkazu
            inputField.setText("");
        }
    }
    
//== TESTOVACÍ METODY A TŘÍDY ==================================================

    /***************************************************************************
     * Testovací metoda předvede hraní dané hry
     * prostřednictvím zde definovaného GUI.
     */
    public static void test()
    {
        IGame  gameX = Hra.getHra();
        GUI_01 gui   = new GUI_01(gameX);
    }
    /** @param args Parametry příkazového řádku - nepoužívané. */
    public static void main( String[] args )  {  test();  }
}
